Script flow functions

 

Introduction

Imagine how strange would it be to drive a car that can move only straight forward, without steering wheel to turn it either left or right. Strange would also be to have a phone that can connect only to one phone. And what about a TV you can't change channel on ?

We're lucky to only read about these funny cases where the lack of choice could lead to a not very happy end. While computer software likes happy ends, it contains variety of functions, and some of them deal with flow control. Giving ability of choice, programmers make software interactive. Meaning, user is not watching a movie, but participating in interactive sessions between software and it's user.

 

The car will take you almost wherever you want, thanks to the steering wheel. To make MMB application go at desired path, you'll use steering wheel too - flow control functions !

MMB uses two ways of controlling script flow: If statements and For..Next loops.



If statements

Introduction

Making decisions is what if statements are all about. By reading road signs you'll adjust the speed or direction of your vehicle. Hitting the ball in the right direction will make a goal for your team. Adding extra pepper will make your meal spicey.


As you can see from the image above, depending on what you put on the house of playing cards - that house will either keep standing or collapse.

MMB uses variable label as platform for variable value (object you put on the platform).


Basic If statement syntax


Script code lines consist of:

a) writing If clause:

If

b) opening parenthesis with variable label:

(object$

c) followed by equal sign:

=

d) then writing contents (value) of variable at the end, behind label and equal sign, followed by closing parenthesis:

'rock')

e) and adding of then clause at the end of the first line:

Then


Put together, first line of if statement will look like this:

If (object$='rock') Then

This line instructs MMB to perform certain actions if content of string variable object$ matches exactly the string specified inside single quotes (in this case: rock).

And what if variable really matches specified content ? After the line above, you will continue writing script lines that will be executed in the case of content match:

MyText$='Object put to platform is: '+object$
Message("","MyText$")

When you're done writing code lines that should be performed in match case, you can use another clause:

Else

...and continue writing lines that should be performed if variable doesn't match specified content. For example:

MyText$='Unknown object has been put to platform'
Message("","MyText$")

Adding of else clause and script lines of else case are optional. But, whatever you decide, you must tell MMB when you're done with if statement, by adding the end clause:

End


Let's see now how entire if statement code looks like !

If (object$='rock') Then
   MyText$='Object put to platform is: '+object$
    Message("","MyText$")

Else
    MyText$='Unknown object has been put to platform'
    Message("","MyText$")
End


Translated: if content of string variable object$ is the rock, text assigned to MyText$ string variable will be "Object put to platform is: rock" and it'll be displayed in MMB's message box.
But if content of string variable object$ is something else, text assigned to MyText$ string variable will be "Unknown object has been put to platform" and it'll be displayed in MMB's message box. All lines put after Else clause will be executed only when If clause is false.

Of course, you don't have to use Else if you don't want to:

If (object$='rock') Then
   MyText$='House of cards has collapsed !'
    Message("","MyText$")
   Return()

End

These code lines will display message box with text "House of cards has collapsed !" if object$ variable contents is rock , and after that it'll call Return() command to stop going any further in script code lines (both in & out of if statement code lines).


Multiple If statements


Another option is to use multiple If statements, to make more decisions:

If (TankVolume=10) Then
    Message(" Please add some more fuel ","")
   Return()

End
If (TankVolume=50) Then
    Message(" Tank is half full ","")
   Return()

End

If (TankVolume=100) Then
    Message(" Tank is full ! ","")
   Else
   Message("Tank status unknown","")
End


The first thing you'll notice above is - we're using numerical variables. The principle is completely the same as for string variables. Here we take numerical variable TankVolume that contains some value. Once it goes through multiple if statements, we'll have message box pop up even when neither of if cases is
true, because last if statement also includes Else clause, containing the code that will be executed if code lines didn't go in any other direction.


Using value range in If statements


It wouldn't be very handy to have only fixed values in if statements:

 

We would need too many if cases to handle all sub-values. This looks better:

 

So, not only equal operator is available, but variety of others:

Operator
Name
=
equals
<>
different than

<

less than
>
greater than
<=
less than or equal
=>
more than or equal

 

Put into code lines, here's how these operators look like:

If (Volume<10) Then
    Message("Volume is less than 10 !","")
End

(displays message box if content of numerical variable Volume is under 10)

If (Volume<=49) Then
    Message("Volume is under 50.","")
End

(displays message box if content of numerical variable is 49 or under that number)

If (Volume<>100) Then
    Message("Volume is not 100.","")
End

(displays message box if content of numerical variable is different than 100)


Multiple cases in If statements


Another neat feature of if statements in MMB is ability to use more conditions in one line.


There are two available operators:

Operator
Name
&
and
|
or

To use these, you'll start by writing an If clause:

If

...opening parenthesis with first variable label:

(OldUser$

...followed by equal sign:

=

...then writing content (value) of variable at the end, behind label and equal sign:

'John'

...and adding either & or | operator:

&

After writing this, you'll start adding the next case, without opening new parenthesis, but continuing writing variable name inside current one:

NewUser$

...followed by equal sign:

=

...and writing contents (value) of variable at the end, behind label and equal sign:

'Peter'

Now you can either continue adding another case, or finish the if statement code line by closing parenthesis:

)

... and adding Then clause at the end of the first line:

Then

Put together, first line of If statement with more conditions looks like this:

If (OldUser$='John' & NewUser$='Peter') Then


And what will this code line do ? Check value of OldUser$ for a match with name John. If the match exists, it'll go and check if value of NewUser$ matches name Peter. If that's the case, MMB will perform code lines entered after Then clause.

Here's an example with | (or) operator:


If (OldUser$='John' | NewUser$='Peter') Then


Case will be positive if either OldUser$ or NewUser$ matches the case, and MMB will perform code lines entered after Then clause. If neither match, if statement code lines are ignored.


And there are even more combinations here ! Variables can be compared with other variables, multiple cases can be combined between numerical and string variables, using of <> operator is available not only for numerical, but also for string variables. Nested if statements (one in another) are also available here.

Let's see how these features work, one by one...


Variable vs. Variable


In many occasions, values are stored in variables. It's possible to compare two variables in the if statements and check do they match:

If (User1$=User2$) Then
    Message("Users are identical !","")
End


Example above compares 2 string variables (User1$, User2$) and if they match, message box is displayed, saying "Users are identical !". Here's one example that uses numerical variables:


If (CurrentLevel>Recommended) Then
    Message("Level is higher than recommended !","")
End


Example checks if value of numerical variable CurrentLevel is higher than value of numerical variable Recommended. If it is, message box is displayed, saying "Level is higher than recommended !"


If statements with mixed variables


Another advantage of if statements with multiple cases is ability to look for matches on both string and numerical variables inside the same if statement. Here's an example:


If (UserName$='Bundy' & UserHeight>197) Then
    Message("Bundy is higher than 197 cm","")
End


Code above checks match on 2 variables - string variable UserName$ and numerical variable UserHeight. If string variable contains name Bundy, and if numerical variable content is higher than 197, message box will display: "Bundy is higher than 197 cm".


Checking match with <>


In some cases you won't be interested in checking value range or match, but only see if either numerical or string variable differs from specified value. One of usual examples is checking of passwords, where your program only wants to know if user input matches (either variable or fixed) password. So let's see how this works:

If (UserInput$<>'SoftwareRegKey') Then
    Message("Entered software reg key is not valid !","")
End


You remember <> operator from previous paragraphs - and it's by default used for numerical variables. But in MMB you can use <> to search for a difference on string variables too.
Just for the record, here's an example with numerical variable:


If (MyHeight<>YourHeight) Then
    Message("We have different height !","")
End


Here we check the difference between two numerical variables. If difference exists, message box is displayed, saying: "We have different height !".


Nested If statements


In addition to multiple if statements, here's another feature that is actually longer version of multiple case if statement. It's possible to enter second if statement inside of the first one and have parts of the code executed depending on case match.


If (UserName$='Bundy') Then
   If (UserHeight>197) Then
       Message("Bundy is higher than 197 cm","")
   End
End


Although you could replace this example with shorter version:

If (UserName$='Bundy' & UserHeight>197) Then
    Message("Bundy is higher than 197 cm","")
End


...by using nested If statements it's possible to execute some other code inside of the first statement, that doesn't depend on the second if statement match case:


If (UserName$='Bundy') Then
 Message("Hello Bundy !","")
   If (UserHeight>197) Then
       Message("Bundy is higher than 197 cm","")
   End
End


Code lines above will check if string variable UserName$ matches name "Bundy". If it does, message box with "Hello Bundy !" text is displayed. After that, second (nested) if statement is checked with numerical variable UserHeight. If number is higher than 197, second message box will be displayed, saying: "Bundy is higher than 197 cm".
So, even if Bundy is not higher than 197 cm, first (Hello Bundy !) message box will be displayed. The same principle goes for code lines entered below entire second if statement.

Notice where nested if statements are entered - End clause of previous if statement is not put above 'em, but below, encapsulating nested statements. You can add as many nested statements as you like and brake further execution with Return() command:


If (UserName$='Bundy') Then
 Message("Hello Bundy !","")
    If (UserHeight>197) Then
       Message("Bundy is higher than 197 cm","")
    
    If (UserWeight>110) Then
           Message("Bundy weighs more than 110 kilos","")
                     Return()
         End
       Message("Bundy weighs less than/or 110 kilos","")

    End
End


If statements are marked with different colors so you can see which End clause belongs to which statement. First message box is displayed if UserName$ matches name "Bundy". Second message box is displayed if numerical variable UserHeight contains number higher than 197. Now, third if statement (marked red) is interesting - if numerical variable UserWeight is higher than 110, message box will display "Bundy weighs more than 100 kilos" and that's where execution of all if statements is stopped with Return() . But if UserWeight is not greater than 110, message box will display "Bundy weighs less than/or 110 kilos".

For..Next loops


Introduction


Keep walking.

Could you repeat that ?

Make 10 circles around the stadium !


Above mentioned expressions are used every day, and nobody is used to say:


Keep making loops with your legs.

Could you loop what you just said ?

Loop around the stadium 10 times !


Although it sounds funny, at the same time it's true - moving one leg in front of another repeatedly is a loop, just as circulating around the stadium. Engines use loops too:


Millions of people work on factory lines, having loops as their work basics:

 

And in all these cases there's no help - actions must be repeated manually, sometimes with help from automatized machines. And talking about machines, did computers borrow this process too ? Yep, they did ! Programmers had enough of hard manual work, repeating the same routines again and again... so they added looping !

Loops & MMB


 

That's how it's done in MMB ! Pour commands, just like syrup, until you have enough !


To use loops, you'll start by writing a For clause:

For

...adding a numerical variable that will be used as a counter:

Counter

...followed by equal sign:

=

...then writing starting value for a range of Counter variable :

1

...and adding To clause:

To

After this, you'll write an ending value of range for Counter variable:

100

Let's see now how the first for..next loop line looks like:

For Counter=1 To 100


Line above tells MMB that everything written below should be repeated. And how many times ? From the starting value of numerical variable, to an ending value of that variable.

After setting loop properties with code line above, you can start writing code lines that will be performed in the loop. In code sample above, commands would be executed 100 times (as specified through Counter numerical variable). So, let's write some already-known commands:

var$='Hello from loop, this is first message box'
Message("","var$")
var$='Hello from loop, this is second message box'
Message("","var$")

These lines will display two message boxes. One saying Hello from loop, this is first message box, and the second one saying Hello from loop, this is second message box . If these lines were executed without loop, message boxes would appear only once each. But ! Specifying loop using For Counter=1 To 100, we said to MMB: repeat showing these message boxes hundred times each ! Every var$ would be assigned 100 times. Every message box would appear 100 times.

Once you're done writing commands that should be executed in loop, it's necessary to mark the end of such code block, otherwise MMB wouldn't know what's inside and outside of the for..next loop. And running entire program in one big loop surely ain't something you want.
Marking the end of for..next loop code block is done using Next clause. Remember that numerical variable Counter, used for setting number of loop repeats ? You'll write label of that variable behind the Next clause:

Next Counter

It's like saying to MMB: once you're done performing lines in for..next block, update value of numerical variable used as a counter (it goes either +1 or -1, more about it below) and start performing block lines all over again !

Here's colorized summary of for..next loop code lines:

For Counter= 1 To 100
   var$='Hello from loop, this is first message box'
    Message("","var$")
    var$='Hello from loop, this is second message box'
    Message("","var$")

Next Counter

Loop clauses For, To, Next are marked blue.
Numerical variable that serves as a loop counter is labeled Counter and is marked red.
Range for loop counter is marked green, in this case 0 - 100.
All code lines that are executed repeatedly in loop are pink - var$, Message("","")

Loop counter

If you stand by the road and count cars passing by, you'll start from the first car and think of number "1" . When another car passes by, you'll add 1 to previous number and keep waiting for the next car. Until you get bored and say: Hey, I had enough of this loop !

Another case is a stopwatch in one hand, a gun in another hand and dozen of racers on track at some big stadium. You count down numbers...

10...9...8...7...6...5...4...3...2...1...BANG !


Both cases are being used in MMB for..next loops for counting purposes. Already mentioned next clause does exactly what people do when counting things - it either adds 1 or substracts 1 to/from some number (represented as numerical variable). That way, MMB's numerical variable "remembers" number of repeats it performed on code block inside loop and once it reaches ending value of range - loop is over, and BANG is heard (just kidding).


Sample above uses numerical variable i as a counter. Loop code block is performed 5 times, and after that, MMB continues executing code lines below For..Next loop block. It means that message box saying "After-loop message! !" will not be displayed before loop block is performed n times (in this case - 5).

Counting cases above mention both positive (+1) and negative (-1) counting. Examples of positive counting have been used before, but here's another one:

For Love=1 To 10
  var$='I love MMB'
  Message("","var$")
Next Love

That's when you start with lower value (Love=1) and end with higher value (To 10).

Counting in opposite (negative, -1) direction can also be used:

For Seconds=10 To 1
  var$='Woof !'
  Message("","var$")
Next Seconds

Here you start with higher value (Seconds=10) and end with lower value (to 1).

MMB compares starting and ending value, automatically deciding in what direction should it go. Of course, it's not necessary to use number 1 as either starting or ending point:

For MileAge=90 To 100
  var$='Almost there!'
  Message("","var$")
Next MileAge

This example uses 90 as a loop starting value and 100 as an ending value. So how many times will loop code be repeated ? Yep ! 10 !


And it's not like you'll just use for..next loop to execute fixed code ! While MMB uses numerical variables for counters, and numerical variables can be used wherever you want in your code, current value of loop counter can be used for some dynamic actions.

It's like walking from one runner to another before the race, giving 'em t-shirt labels saying "You're number 1", "You're number 2", "You're number 23473"...

Let's take a look at loop code sample:

For Runner=1 To 10
  var$='You are runner no. '+CHAR(Runner)
  Message("","var$")
Next Runner


Loop above uses numerical variable Runner to execute some code lines 10 times.
Assigning of text to string variable var$ is interesting - it first sets text "You are runner no." and then uses CHAR function to convert current value of numerical variable Runner (used as a loop counter, remember ?) to act as a string, when + operator assigns it to var$ .

The result ? Loop will show message box 10 times, but contents will be adjusted according to current value of loop counter. So, message box will every time read different numerical value:

You are runner no. 1
You are runner no. 2
You are runner no. 3

You are runner no. 4
You are runner no. 5
You are runner no. 6

You are runner no. 7
You are runner no. 8
You are runner no. 9

You are runner no. 10

This ability is very useful for intensive processing of items, names, records, files... you only change index number and everything else goes through the same block of commands inside the loop. A true time saver - imagine writing & maintaining the same block of commands for every item you want to process ! When you get into using loops, you will never throw 'em away ;)

TIP! There is also an option to dynamically change the To ending value from within the For..Next loop counter. Thanks to this you can prematurely terminate the For..Next loop in a certain conditions and without the need to call Return() or Break() function.

EXAMPLE OF USAGE:
The below script script is useless, but it can show you how to dynamically change the To value in For...Next loop. Initially, the loop should be repeated 5 times, but after the third loop, the loop range is changed to 3 and therefore the For..Next is terminated.

**This loop is terminated after 3 loops...
maxloop=5
For i=1 To
maxloop
  Message("in loop","")
  If (i=3) Then
    ** maxloop is now 3!!
    
maxloop=i
  End
Next i
Message("outside loop","")

Loop utilities

Once in a while it's possible to have a need for an endless loop that will, for example, check some things (system info, file existence, user input...) occasionally and without specific number of repeats. That's when Infinite loops come into action:

For check=1 To Infinity
  check=check+1
  DisplayValue("Text","check")
Next check

Code sample above uses Infinity clause as an ending value of numerical variable counter, thus making definition of loop saying "Start with 1 and never stop" . Of course, that never is hypothetical - loop is repeated while your program is running and project page is not changed. If either user exits program, changes page or computer shuts program down, loop will reach the very end of it's infinity ;)

Issue emerging from using this kind of loops is - program functioning while such loop is being performed. Will everything be blocked while infinity loop keeps repeating ?

Not really, but to allow other objects & scripts to work properly it is recommended to use flow commands:

Refresh() - gives time to other threads being used by program to perform their actions
Pause("") - stops execution of code block for specified amount of time (in msecs)

Read more about these in command descriptions, here's how they work for loops:

For check=1 To Infinity
  check=check+1
  DisplayValue("Text","check")
  Refresh()
Next check


Put after loop code block, Refresh() gives time to other program threads before starting another repetition of code block.


For check=1 To Infinity
  check=check+1
  DisplayValue("Text","check")
  Pause("500")
Next check

Put after loop code block, Pause("500") makes delay (in this case 500 miliseconds - half a second) before repeating code block. It means that loop code will be executed every half a second. Even higher delay periods are recommended for tasks where real-time check-ups are not of a critical importance.

Another issue related to infinity loops in service of check-ups is a case when some condition has been fulfilled and loop should be stopped. In that case Return() command is a great help, while it stops further execution of entire script:

For check=1 To Infinity
  check=check+1
  DisplayValue("Text","check")
  If (UserInput$='GO') Then
    Return()
  End
  Pause("500")
Next check

In case you don't want to stop execution of entire script, but only jump from the current For..Next loop, use Break() command instead. The execution of code will continue after "Next n" line of the For..Next loop where the Break() function was used.

Loop above is "smart" enough to perform repetition as long as value of string variable UserInput$ doesn't match fixed value "GO" . When UserInput$ contains correct value, if statement will call Return() command and loop (together with any code lines below the loop block) will be stopped. This routine is oftenly being used to call some other script with RunScript and ScriptTimer commands:

For check=1 To Infinity
  check=check+1
  DisplayValue("Text","check")
  If (UserInput$='GO') Then
    RunScript("InputCorrect")
    Return()
  End
  Pause("500")
Next check

Read more about RunScript and ScriptTimer in their command descriptions.

That's about everything to tell on the loop subject ! If you're a beginner in MMB scripting, loops probably won't be the first subject you'll get into, and instead you'll use manual code repetitions. But as you make progress in MMB scripting learning curve, loops will come up as a very comfortable solution for tasks with intensive scripting.

 


MMB Scripting Unleashed by Bokzy, 2003 :: All rights reserved :: http://www.bokzy.com